#include "sk_game_item.h"
#include "sk_swap.h"

#include <QDebug>
#include <QPainter>
#include <QString>
#include <QGraphicsItem>
#include <QGraphicsScene>


namespace sk
{

    // BASE CLASS
GameItem::GameItem(GameItem * parent, int ind /*= 0*/)
{
    _parent = parent;
    _ind    = ind;
    _canSwapChilds = _canCloneChilds = false;
    _ci = _cj = 0;
    _sceneItem = 0;
}

GameItem::~GameItem()
{
	resetSceneItem();
    QHash<int, GameItem*>::iterator it;
    for (it = _childItems.begin(); it != _childItems.end(); ++it)
    {
        delete it.value();
    }
}

void GameItem::resetSceneItem()
{
    if (_sceneItem)
    {
        _sceneItem->scene()->removeItem(_sceneItem);
        _sceneItem = 0;
    }
}

void GameItem::performForChilds(GameItemOperation op)
{
    QHash<int, GameItem*>::iterator it;
    for (it = _childItems.begin(); it != _childItems.end(); ++it)
    {
        if (!it.value()->perform(op))
        {
                it.value()->performSpecial(op);
        }
        it.value()->performForChilds(op);
    }
}

bool GameItem::perform(GameItemOperation op)
{	
    if (op == OP_RESET_SCENE_ITEM)
    {
        resetSceneItem();
        return true;
    }
    return false;
}

bool GameItem::performSpecial(GameItemOperation op)
{
	return false;
}

void * GameItem::getUpward(GameItemType type)
{
    void * res = 0;
    GameItem * item = this;
    while (item)
    {
        res = item->get(type);
        if (res)
        {
            return res;
        }
        item = item->parent();
    }
    return 0;
}

QSize GameItem::sizeHint(const QStyleOptionViewItem & option, int row, int column)
{
    return QSize(100, 30);
}

QGraphicsItem * GameItem::createSceneItem()
{
    return 0;
}

void GameItem::onPropertyChange(GameItemProperty *)
{
}

GameItem * GameItem::parent()
{
    return _parent;
}

void * GameItem::get(GameItemType)
{
    return 0;
}

QVector<int> GameItem::getIndex()
{
    // TODO : can be optimised a bit
    QVector<int> res;
    GameItem * item = this;
    while (item)
    {
        res.prepend(item->index());
        item = item->parent();
    }
    return res;
}

int GameItem::index() const
{
    return _ind;
}

void GameItem::setIndex(int ind)
{
    _ind = ind;
    if (_sceneItem)
    {
        _sceneItem->update();
    }
}

int GameItem::numChilds()
{
    return 0;
}

int GameItem::numChildsForProxy(int)
{
    return 0;
}

GameItem * GameItem::getChildItemForProxy(int, int)
{
    return 0;
}

void GameItem::fillBg(QPainter * painter, const QStyleOptionViewItem & option, int row, int column)
{

    if (option.state & QStyle::State_MouseOver)
    {
        painter->fillRect(option.rect, Qt::gray);
    }
    else
    if (option.state & QStyle::State_Selected)
    {
        painter->fillRect(option.rect, Qt::darkGray);
    }
    else
    {
        painter->fillRect(option.rect, Qt::white/*row & 1 ? QColor(246, 246, 246) : Qt::white*/);
    }
}

GameItem * GameItem::createItem(void * params)
{
    return 0;
}

void GameItem::paint(QPainter * painter, const QStyleOptionViewItem & option, int row, int column)
{
    painter->save();
    fillBg(painter, option, row, column);
    painter->restore();
}

void GameItem::paintText(QPainter * painter, const QStyleOptionViewItem & option, QString * text, int row, int column)
{
    painter->save();

    fillBg(painter, option, row, column);

    if (column == 0)
    {

        if ( (option.state & QStyle::State_MouseOver) || (option.state & QStyle::State_Selected) )
        {
            painter->setPen(Qt::white);
        }
        else
        {
            painter->setPen(Qt::black);
        }

        painter->drawText(option.rect, *text, QTextOption(Qt::AlignLeft | Qt::AlignVCenter));
    }

    painter->restore();
}

void GameItem::doDelete()
{
    if (!canDeleteFromProjectExplorer())
    {
        return;
   } 
    GameItem * p = parent();
	int ind = index();
	int n = p->numChilds();
    p->doDeleteChild(ind);
	p->_childItems.erase(p->_childItems.find(ind));
	for (int i = ind + 1; i < n; ++i)
	{
		QHash<int, GameItem *>::iterator it = p->_childItems.find(i);
		if (it != p->_childItems.end())
		{
			p->_childItems[i - 1] = it.value();
			it.value()->setIndex(i - 1);
			p->_childItems.erase(it);
		}
	}    
    delete this;
}

void GameItem::doDeleteChild(int ind)
{

}

void GameItem::doDeleteChildForProxy(int, int)
{

}

bool GameItem::canDeleteFromProjectExplorer()
{
    return false;
}

void GameItem::onDoubleClickInProjectExplorer()
{

}

GameItem * GameItem::child(int i)
{
    if (0 == numChilds())
    {
        return 0;
    }
    if (_childItems.contains(i))
    {
        return _childItems[i];
    }
    GameItem * res = getChildItem(i);
    if (!res)
    {
        return 0;
    }
    _childItems[i] = res;
    return res;
}

GameItem * GameItem::getChildItem(int i)
{
    return 0;
}

int GameItem::numProperties()
{
    return 0;
}

GameItemProperty * GameItem::getProperty(int ind)
{
    return 0;
}

bool GameItem::validIndexesForSwap(int i, int j)
{
    if (i == j)
    {
        return false;
    }
    if (i > j)
    {
        sk::swap(i, j);
    }
    Q_ASSERT(i < j);
    if (i < 0 || j >= numChilds())
    {
        return false;
    }
    return true;
}

bool GameItem::swapChilds(int i, int j)
{
    if (!canSwapChilds() || !validIndexesForSwap(i, j))
    {
        return false;
    }
    _ci = child(i);
    _cj = child(j);
	_childItems[i] = _cj;
	_cj->setIndex(i);
	_childItems[j] = _ci;
	_ci->setIndex(j);
    doSwapChilds(i, j);
    return true;
}

void GameItem::doSwapChilds(int, int)
{
}

void GameItem::doSwapChildsForProxy(int, int, int)
{
}

bool GameItem::canCloneChilds() const
{
    return _canCloneChilds;
}

bool GameItem::canSwapChilds() const
{
    return _canSwapChilds;
}

void GameItem::setCanSwapChilds(bool canSwap)
{
    _canSwapChilds = canSwap;
}

void GameItem::setCanCloneChilds(bool canClone)
{
    _canCloneChilds = canClone;
}

GameItem * GameItem::cloneChild(int ind)
{
    if (!canCloneChilds())
    {
        return 0;
    }
    doCloneChild(ind);
    return child(numChilds() - 1);
}

void GameItem::doCloneChild(int ind)
{
}

void GameItem::doCloneChildForProxy(int proxyInd, int ind)
{
}

#if 0
void GameItem::setPropertiesModel(QAbstractItemModel * model)
{
    _propertiesModel = model;
}

QAbstractItemModel * GameItem::propertiesModel() const
{
    return _propertiesModel;
}
#endif
} // namespace sk
